package integration;

import static org.junit.Assert.*;

import java.awt.event.ActionEvent;
import java.lang.reflect.Field;
import javax.swing.JButton;
import org.junit.Before;
import org.junit.Test;

import blackjack.MyMath;

/* ASCOLTATORE METHOD SPECIFICATION
 * 1.	Define the behavior of application buttons; the action performed is different for each event type; 
 * 2.	START EVENT:
 * 			a.	start new game and/or reset old one;
 * 			b.	give 2 cards to player and show them on screen;
 * 			c. 	verify player "blackjack"; in this case a notification is shown;
 * 			d.	in case of "blackjack", the game ends and 1 point is assigned to player;
 * 3.	HIT EVENT:
 * 			a.	1 new card is taken by the player;
 * 			b. 	verify player "blackjack" or "busted"; in these cases a notification is shown;
 * 			c.	in case of "blackjack", the game ends and 1 point is assigned to player;
 * 			d. 	in case of "busted", the game ends and 1 point is assigned to cpu;
 * 			e. 	if not pressed START before, it does nothing; a notification is shown;
 * 4.	STAND EVENT:
 * 			a. 	player game ends and cpu starts to play;
 * 			b. 	in case of victory, 1 point is assigned to player;
 * 			c.	in case of defeat, 1 point is assigned to cpu;
 * 			d. 	in case of tie, the game ends and no points are assigned;
 * 			e. 	if not pressed START before, it does nothing; a notification is shown.
 *
 * TEST 01_1: randList = {5,9, 2,8} 							start	press twice [reset game]		RES: player = 10 && player != 14
 * TEST 01_2: randList = {1,10, 4,12,9} 						start	blackjack [player wins]			RES: player wins; out = true
 * TEST 01_3: randList = {1,1} 									start	'A' correction [2 aces] 		RES: player = 12; not busted
 * TEST 02_1: player = 6; out=false; randList = {5} 			hit		generic "hit" event				RES: player = 11
 * TEST 02_2: player = 13; out=false; randList = {1} 			hit		'A' correction [last card]		RES: player = 14; not busted
 * TEST 02_3: player = 14; out=false; randList = {8, 10,3,11} 	hit		busted							RES: player loses; out = true
 * TEST 02_4: player = 14; out = false; randList = {7, 10,9,6} 	hit		blackjack [player wins]			RES: player = 21; player wins; out = true
 * TEST 02_5: randList = {11,4,7} 								hit		not started game				RES: player = 0
 * TEST 03_1: player = 16; out=false; randList = {7,5,12}		stand	player wins						RES: player wins; out = true
 * TEST 03_2: player = 17; out=false; randList = {4,8,12} 		stand	player loses (not busted)		RES: player loses; out = true
 * TEST 03_3: player = 18; out=false; randList = {4,9,5} 		stand	player ties						RES: player ties; out = true
 * TEST 03_4: randList = {3,10} 								stand	not started game				RES: player = 0; not lose
 * TEST 04_1: press_start; randList = {1,4,12} 					multi	'A' correction [first card]		RES: player = 15; not busted
 * TEST 04_2: randList = {5,3,4,6, 10,7,12}						multi	player wins						RES: player = 18; player wins; out = true
 * TEST 04_3: randList = {11,12, 8,5,13, 4,2,6, 9,8}			multi	2 following games				RES: player wins; cpu wins; out = true
 */

public class ascoltatoreTest {
	
	private apple_mod_correct appleRef;
	private apple_mod_correct.ascoltatore listener;
	private ActionEvent start_event = new ActionEvent(new JButton(), 1, "start");
	private ActionEvent hit_event = new ActionEvent(new JButton(), 2, "hit");
	private ActionEvent stand_event = new ActionEvent(new JButton(), 3, "stand");
	private Field player, state_player, state_cpu, out;
	
	@Before
	public void setUp() throws Exception {
		appleRef = new apple_mod_correct();
		listener = appleRef.new ascoltatore();
		
		player = (appleRef.getClass()).getDeclaredField("player");
		player.setAccessible(true);
		
		state_player = (appleRef.getClass()).getDeclaredField("state_player");
		state_player.setAccessible(true);
		
		state_cpu = (appleRef.getClass()).getDeclaredField("state_cpu");
		state_cpu.setAccessible(true);
		
		out = (appleRef.getClass()).getDeclaredField("out");
		out.setAccessible(true);
	}

	/* TEST 01_1: randList = {5,9, 2,8}
	 * DESC: press START twice [reset game]
	 * RES: player = 10 && player != 14 */
	@Test
	public void testAscoltatore_01_1() throws Exception {
		// START preconditions
		double[] randList = {5,9, 2,8};
		MyMath.set_randList(randList);
		// END preconditions
		
		int old_state_player = state_player.getInt(appleRef);
		int old_state_cpu = state_cpu.getInt(appleRef);
		
		listener.actionPerformed(start_event);
		listener.actionPerformed(start_event);
		
		// player is the sum of the last 2 cards
		assertEquals(10,player.getInt(appleRef));
		
		// idle game [no point is assigned]
		assertEquals(old_state_player,state_player.getInt(appleRef));
		assertEquals(old_state_cpu,state_cpu.getInt(appleRef));
	}
	
	/* TEST 01_2: randList = {1,10, 4,12,9}
	 * DESC: blackjack on START [player wins]		
	 * RES: player wins; out = "true" */
	@Test
	public void testAscoltatore_01_2() throws Exception {
		// START preconditions
		double[] randList = {1,10, 4,12,9};
		MyMath.set_randList(randList);
		// END preconditions
		
		int old_state_player = state_player.getInt(appleRef);
		int old_state_cpu = state_cpu.getInt(appleRef);
		
		listener.actionPerformed(start_event);
		
		// player score is 21
		assertEquals(21,player.getInt(appleRef));
		
		// player wins the game [because cpu automatically plays]
		assertEquals(old_state_player+1,state_player.getInt(appleRef));
		assertEquals(old_state_cpu,state_cpu.getInt(appleRef));
		assertEquals(true,out.getBoolean(appleRef));
	}
	
	/* TEST 01_3: randList = {1,1}
	 * DESC: 'A' correction [2 aces]	
	 * RES: player = 12; not busted */
	@Test
	public void testAscoltatore_01_3() throws Exception {
		// START preconditions
		double[] randList = {1,1};
		MyMath.set_randList(randList);
		// END preconditions
		
		int old_state_player = state_player.getInt(appleRef);
		int old_state_cpu = state_cpu.getInt(appleRef);
		
		listener.actionPerformed(start_event);
		
		// player score is 12
		assertEquals(12,player.getInt(appleRef));
		
		// player not busted
		assertEquals(old_state_player,state_player.getInt(appleRef));
		assertEquals(old_state_cpu,state_cpu.getInt(appleRef));
	}
	
	/* TEST 02_1: player = 6; randList = {5}; out = "false";
	 * generic HIT event
	 * RES: player = 11; out = "true" */
	@Test
	public void testAscoltatore_02_1() throws Exception {
		// START preconditions
		double[] randList = {5};
		MyMath.set_randList(randList);
		player.setInt(appleRef,6);
		out.setBoolean(appleRef,false);
		// END preconditions
		
		int old_state_player = state_player.getInt(appleRef);
		int old_state_cpu = state_cpu.getInt(appleRef);
		int old_player = player.getInt(appleRef);	// player score before "hit_event"
		
		listener.actionPerformed(hit_event);
		
		// player score is increased by 5
		assertEquals(old_player+5,player.getInt(appleRef));
		
		// idle game [no point is assigned]
		assertEquals(old_state_player,state_player.getInt(appleRef));
		assertEquals(old_state_cpu,state_cpu.getInt(appleRef));
	}
	
	/* TEST 02_2: player = 13; randList = {1}; out = "false"
	 * HIT 'A' card -> correction needed
	 * RES: player = 14; not busted */
	@Test
	public void testAscoltatore_02_2() throws Exception {
		// START preconditions
		double[] randList = {1};
		MyMath.set_randList(randList);
		player.setInt(appleRef,13);
		out.setBoolean(appleRef,false);
		// END preconditions
		
		int old_state_player = state_player.getInt(appleRef);
		int old_state_cpu = state_cpu.getInt(appleRef);

		listener.actionPerformed(hit_event);
		
		// player score is increased by 1 (if value=11, it is increased by 11) 
		assertEquals(14,player.getInt(appleRef));
		
		// no point is assigned (if value=11, player is "busted" and cpu wins)
		assertEquals(old_state_player,state_player.getInt(appleRef));
		assertEquals(old_state_cpu,state_cpu.getInt(appleRef));
	}
	
	/* TEST 02_3: player = 14; randList = {8}; out = "false"
	 * DESC: player busted
	 * RES: player loses; out = "true" */
	@Test
	public void testAscoltatore_02_3() throws Exception {
		// START preconditions
		double[] randList = {8, 10,3,11};
		MyMath.set_randList(randList);
		player.setInt(appleRef,14);
		out.setBoolean(appleRef,false);
		// END preconditions
		
		int old_state_player = state_player.getInt(appleRef);
		int old_state_cpu = state_cpu.getInt(appleRef);
		
		listener.actionPerformed(hit_event);
		
		// player "busted"
		assertEquals(true,player.getInt(appleRef)>21);
		
		// player busted
		assertEquals(old_state_player,state_player.getInt(appleRef));
		assertEquals(old_state_cpu+1,state_cpu.getInt(appleRef));
		assertEquals(true,out.getBoolean(appleRef));
	}
	
	/* TEST 02_4: player = 14; randList = {7, 10,9,6}; out = "false"
	 * DESC: blackjack [player wins]
	 * RES: player = 21; player wins; out = "true"
	 */
	@Test
	public void testAscoltatore_02_4() throws Exception {
		// START preconditions
		double[] randList = {7, 10,9,6};
		MyMath.set_randList(randList);
		player.setInt(appleRef,14);
		out.setBoolean(appleRef,false);
		// END preconditions
		
		int old_state_player = state_player.getInt(appleRef);
		int old_state_cpu = state_cpu.getInt(appleRef);
		
		listener.actionPerformed(hit_event);
		
		// player scores Blackjack
		assertEquals(21,player.getInt(appleRef));
		
		// player wins [do not burst]
		assertEquals(old_state_player+1,state_player.getInt(appleRef));
		assertEquals(old_state_cpu,state_cpu.getInt(appleRef));
		assertEquals(true,out.getBoolean(appleRef));
	}
	
	/* TEST 02_5: randList = {11,4,7}
	 * DESC: press hit; not started game
	 * RES: player = 0 */
	@Test
	public void testAscoltatore_02_5() throws Exception {
		// START preconditions
		double[] randList = {11,4,7};
		MyMath.set_randList(randList);
		// START preconditions
		
		listener.actionPerformed(hit_event);
		
		int old_state_player = state_player.getInt(appleRef);
		int old_state_cpu = state_cpu.getInt(appleRef);
		
		// player score is 0
		assertEquals(0,player.getInt(appleRef));
		
		// idle game [no point is assigned]
		assertEquals(old_state_player,state_player.getInt(appleRef));
		assertEquals(old_state_cpu,state_cpu.getInt(appleRef));
	}
	
	/* TEST 03_1: player = 16; randList = {7,5,12}; out = "false"
	 * press stand; player wins
	 * RES: player wins; out = "true" */
	@Test
	public void testAscoltatore_03_1() throws Exception {
		// START preconditions
		double[] randList = {7,5,12};
		MyMath.set_randList(randList);
		player.setInt(appleRef,16);
		out.setBoolean(appleRef,false);
		// END preconditions
		
		int old_player = player.getInt(appleRef);
		int old_state_player = state_player.getInt(appleRef);
		int old_state_cpu = state_cpu.getInt(appleRef);
		
		listener.actionPerformed(stand_event);
		
		// player "stand"
		assertEquals(old_player,player.getInt(appleRef));
		
		// player wins the game
		assertEquals(old_state_player+1,state_player.getInt(appleRef));
		assertEquals(old_state_cpu,state_cpu.getInt(appleRef));
		assertEquals(true,out.getBoolean(appleRef));
	}
	
	/* TEST 03_2: player = 17; randList = {3,8,12}; out = "false"
	 * DESC: press stand
	 * RES: player loses (not busted); out = "true" */
	@Test
	public void testAscoltatore_03_2() throws Exception {
		// START preconditions
		double[] randList = {3,8,12};
		MyMath.set_randList(randList);
		player.setInt(appleRef,17);
		out.setBoolean(appleRef,false);
		// END preconditions

		int old_player = player.getInt(appleRef);
		int old_state_player = state_player.getInt(appleRef);
		int old_state_cpu = state_cpu.getInt(appleRef);

		listener.actionPerformed(stand_event);

		// player wins the game
		assertEquals(old_player,player.getInt(appleRef));
		
		// player loses
		assertEquals(old_state_player,state_player.getInt(appleRef));
		assertEquals(old_state_cpu+1,state_cpu.getInt(appleRef));
		assertEquals(true,out.getBoolean(appleRef));
	}
	
	/* TEST 03_3: player = 18; randList = {4,9,5}; out = "false"
	 * DESC: press STAND
	 * RES: player ties; out = "true" */
	@Test
	public void testAscoltatore_03_3() throws Exception {
		// START preconditions
		double[] randList = {4,9,5};
		MyMath.set_randList(randList);
		player.setInt(appleRef,18);
		out.setBoolean(appleRef,false);
		// END preconditions
		
		int old_player = player.getInt(appleRef);
		int old_state_player = state_player.getInt(appleRef);
		int old_state_cpu = state_cpu.getInt(appleRef);
		
		listener.actionPerformed(stand_event);

		// player wins the game
		assertEquals(old_player,player.getInt(appleRef));
		
		// no point is assigned
		assertEquals(old_state_player,state_player.getInt(appleRef));
		assertEquals(old_state_cpu,state_cpu.getInt(appleRef));
		assertEquals(true,out.getBoolean(appleRef));
	}
	
	/* TEST 03_4: randList = {3,10}
	 * DESC: not started game
	 * RES: player = 0; not lose */
	@Test
	public void testAscoltatore_03_4() throws Exception {
		// START preconditions
		double[] randList = {3,9,5,2};
		MyMath.set_randList(randList);
		// END preconditions
		
		int old_state_player = state_player.getInt(appleRef);
		int old_state_cpu = state_cpu.getInt(appleRef);
		
		listener.actionPerformed(stand_event);
		
		// player score is 0
		assertEquals(0,player.getInt(appleRef));
		
		// no point is assigned [cpu do not win]
		assertEquals(old_state_player,state_player.getInt(appleRef));
		assertEquals(old_state_cpu,state_cpu.getInt(appleRef));
	}
	
	/* TEST 04_1: first press start; randList = {1,4,12}
	 * 'A' correction [first card]
	 * RES: player = 15; not busted
	 */
	@Test
	public void testAscoltatore_04_1() throws Exception {
		// START preconditions
		double[] randList = {1,4,12};
		MyMath.set_randList(randList);
		// END preconditions
		
		int old_state_player = state_player.getInt(appleRef);
		int old_state_cpu = state_cpu.getInt(appleRef);
		
		listener.actionPerformed(start_event);
		listener.actionPerformed(hit_event);
		
		// player score is increased by 1 (if value=11, it is increased by 11) 
		assertEquals(15,player.getInt(appleRef));
		
		// player not busted
		assertEquals(old_state_player,state_player.getInt(appleRef));
		assertEquals(old_state_cpu,state_cpu.getInt(appleRef));
	}
	
	/* TEST 04_2: randList = {5,3,4,6, 10,7,12}
	 * DESC: FULL GAME
	 * RES: player wins; out = "true" */
	@Test
	public void testAscoltatore_04_2() throws Exception {
		// START preconditions
		double[] randList = {5,3,4,6, 10,7,12};
		MyMath.set_randList(randList);
		// END preconditions
		
		int old_state_player = state_player.getInt(appleRef);
		int old_state_cpu = state_cpu.getInt(appleRef);
		
		listener.actionPerformed(start_event);
		listener.actionPerformed(hit_event);
		listener.actionPerformed(hit_event);
		listener.actionPerformed(stand_event);
		
		// player wins
		assertEquals(old_state_player+1,state_player.getInt(appleRef));
		assertEquals(old_state_cpu,state_cpu.getInt(appleRef));
		assertEquals(true,out.getBoolean(appleRef));
	}
	
	/* TEST 04_3: randList = {11,12, 8,5,13, 4,2,6, 9,8}
	 * DESC: 2 following games
	 * RES: player wins; cpu wins; out = "true" */
	@Test
	public void testAscoltatore_04_3() throws Exception {
		// START preconditions
		double[] randList = {11,12, 8,5,13, 4,2,6, 9,8};
		MyMath.set_randList(randList);
		// END preconditions
		
		int old_state_player = state_player.getInt(appleRef);
		int old_state_cpu = state_cpu.getInt(appleRef);
		
		// first game [player wins]
		listener.actionPerformed(start_event);
		listener.actionPerformed(stand_event);
		
		// second game [cpu wins]
		listener.actionPerformed(start_event);
		listener.actionPerformed(hit_event);
		listener.actionPerformed(stand_event);
		
		// player wins
		assertEquals(old_state_player+1,state_player.getInt(appleRef));
		assertEquals(old_state_cpu+1,state_cpu.getInt(appleRef));
		assertEquals(true,out.getBoolean(appleRef));
	}
	
}
